package logger

import (
	"context"
	"errors"
	"log/slog"
	"os"
	"sync"
	"sync/atomic"
)

var (
	defaultInstance atomic.Pointer[Logger]
	defaultInited   bool
	defaultOnce     sync.Once
	defaultOptions  = Options{
		Level:       defaultLogLevel,
		AddSource:   defaultAddSource,
		CallerSkip:  defaultCallerSkip,
		ReplaceAttr: nil,
	}
)

// Error 记录错误日志(全局默认日志)
func Error(msg string, args ...any) {
	GetDefault().handlerAgent.log(context.Background(), slog.LevelError, msg, args...)
}

// ErrorContext 记录错误日志(全局默认日志)
func ErrorContext(ctx context.Context, msg string, args ...any) {
	GetDefault().handlerAgent.log(ctx, slog.LevelError, msg, args...)
}

// Warn 记录警告日志(全局默认日志)
func Warn(msg string, args ...any) {
	GetDefault().handlerAgent.log(context.Background(), slog.LevelWarn, msg, args...)
}

// WarnContext 记录警告日志(全局默认日志)
func WarnContext(ctx context.Context, msg string, args ...any) {
	GetDefault().handlerAgent.log(ctx, slog.LevelWarn, msg, args...)
}

// Info 记录普通日志(全局默认日志)
func Info(msg string, args ...any) {
	GetDefault().handlerAgent.log(context.Background(), slog.LevelInfo, msg, args...)
}

// InfoContext 记录普通日志(全局默认日志)
func InfoContext(ctx context.Context, msg string, args ...any) {
	GetDefault().handlerAgent.log(ctx, slog.LevelInfo, msg, args...)
}

// Debug 记录调试日志(全局默认日志)
func Debug(msg string, args ...any) {
	GetDefault().handlerAgent.log(context.Background(), slog.LevelDebug, msg, args...)
}

// DebugContext 记录调试日志(全局默认日志)
func DebugContext(ctx context.Context, msg string, args ...any) {
	GetDefault().handlerAgent.log(ctx, slog.LevelDebug, msg, args...)
}

// Log 记录自定义日志(全局默认日志)
func Log(ctx context.Context, level slog.Level, msg string, args ...any) {
	GetDefault().handlerAgent.log(ctx, level, msg, args...)
}

// LogAttrs 记录自定义日志(全局默认日志)
func LogAttrs(ctx context.Context, level slog.Level, msg string, attrs ...slog.Attr) {
	GetDefault().handlerAgent.logAttrs(ctx, level, msg, attrs...)
}

// Handler 获取全局默认日志实例处理器
func Handler() slog.Handler {
	return GetDefault().Handler()
}

// With 基于全局默认日志实例, 返回一个包含给定属性的子日志实例副本
// 如果 args 为空，则返回默认日志
func With(args ...any) *Logger {
	return GetDefault().With(args...)
}

// WithGroup 基于全局默认日志实例, 返回一个包含给定分组名的日志实例副本
// 如果 name 为空，则返回默认日志
// 如果 name 不为空，则返回一个WithGroup的实例副本
// A Handler should treat WithGroup as starting a Group of Attrs that ends
// at the end of the log event. That is,
//
//	logger.WithGroup("s").LogAttrs(ctx, level, msg, slog.Int("a", 1), slog.Int("b", 2))
//
// should behave like
//
//	logger.LogAttrs(ctx, level, msg, slog.Group("s", slog.Int("a", 1), slog.Int("b", 2)))
func WithGroup(name string) *Logger {
	return GetDefault().WithGroup(name)
}

// Use 全局默认日志实例使用中间件, 返回一个包含给定中间件(含继承的中间件)的日志实例副本
func Use(fns ...Middleware) *Logger {
	return GetDefault().Use(fns...)
}

// Wrap slog.log(...) 全局默认日志实例 Wrap 日志入口, 支持临时自定义callerSkip
func Wrap(skip int, ctx context.Context, level slog.Level, msg string, args ...any) error {
	return GetDefault().handlerAgent.Wrap(skip, ctx, level, msg, args...)
}

// WrapAttrs slog.logAttrs(...) 全局默认日志实例 WrapAttrs 日志入口, 支持临时自定义callerSkip
func WrapAttrs(skip int, ctx context.Context, level slog.Level, msg string, attrs ...slog.Attr) error {
	return GetDefault().handlerAgent.WrapAttrs(skip, ctx, level, msg, attrs...)
}

// GetOptions 获取全局默认日志实例配置选项
func GetOptions() Options {
	return GetDefault().GetOptions()
}

// OnClose 注册关闭事件处理器
func OnClose(fn Event) {
	GetDefault().OnClose(fn)
}

// OnError 注册错误事件处理器
func OnError(fn Event) {
	GetDefault().OnError(fn)
}

// SetDefault 设置全局默认日志实例
func SetDefault(log *Logger) {
	if log != nil && log.handlerAgent != nil {
		defaultInstance.Store(log)
		defaultInited = true
	}
}

// GetDefault 获取全局默认日志实例
func GetDefault() *Logger {
	if !defaultInited {
		defaultOnce.Do(func() {
			defaultInited = true
			defaultInstance.Store(NewText(NewStorage(os.Stdout), &defaultOptions))
		})
	}
	return defaultInstance.Load()
}

// GetLevel 获取全局默认日志实例的日志级别
func GetLevel() slog.Level {
	return GetDefault().GetLevel()
}

// SetLevel 设置全局默认日志实例的日志级别(支持动态调整)
func SetLevel(level slog.Level) {
	GetDefault().SetLevel(level)
}

// SetCallerSkip 设置全局默认日志 callerSkip
func SetCallerSkip(skip int) {
	GetDefault().SetCallerSkip(skip)
}

// GetCallerSkip 获取全局默认日志 callerSkip
func GetCallerSkip() int {
	return GetDefault().GetCallerSkip()
}

// Sync 同步全局默认日志实例 Logger.storage (仅同步/不关闭)
//   - 仅对文件日志或实现了Sync()接口的 storage 有效
func Sync() (errs error) {
	return GetDefault().Sync()
}

// SyncAll 同步所有日志实例 Logger.storage (仅同步/不关闭), 关闭后将不再接受日志记录
//   - 仅对文件日志或实现了Sync()接口的 storage 有效
func SyncAll() (errs error) {
	logInstanceMu.Lock()
	defer logInstanceMu.Unlock()
	for _, v := range logInstances {
		if err := v.Sync(); err != nil {
			if errs == nil {
				errs = err
			} else {
				errs = errors.Join(errs, err)
			}
		}
	}
	return errs
}

// Close 关闭全局默认日志实例 Logger.storage (先同步/在关闭), 关闭后将不再接受日志记录
//   - 仅对文件日志或实现了Close()接口的 storage 有效
func Close() (errs error) {
	return GetDefault().Close()
}

// CloseAll 关闭所有日志实例 Logger.storage (先同步/在关闭), 关闭后将不再接受日志记录
//   - 仅对文件日志或实现了Close()接口的 storage 有效
func CloseAll() (errs error) {
	logInstanceMu.Lock()
	defer logInstanceMu.Unlock()
	for _, v := range logInstances {
		if err := v.Close(); err != nil {
			if errs == nil {
				errs = err
			} else {
				errs = errors.Join(errs, err)
			}
		}
	}
	return errs
}

// LastErrors 获取全局默认日志实例 Logger.handler 最近的错误信息
func LastErrors() error {
	return GetDefault().handlerAgent.LastErrors()
}

// LastErrorsAll 获取所有日志实例 Logger.handler 最近的错误信息
func LastErrorsAll() (errs error) {
	for _, v := range logInstances {
		if err := v.LastErrors(); err != nil {
			if errs == nil {
				errs = err
			} else {
				errs = errors.Join(errs, err)
			}
		}
	}
	return errs
}
